技术经验 • dingxiao • 阅读数:4177 • 2019年5月18日 13:01
ESP32自带蓝牙模块,好爽的感觉,测试开始。
运行自带BLE_uart的demo。
#include "BLEDevice.h"
#include "BLEServer.h"
#include "BLEUtils.h"
#include "BLE2902.h"
BLEServer *pServer = NULL;
BLECharacteristic * pTxCharacteristic;
BLECharacteristic * pCharacteristic;
bool deviceConnected = false;
bool oldDeviceConnected = false;
uint8_t txValue = 0;
// See the following for generating UUIDs:
// https://www.uuidgenerator.net/
#define SERVICE_UUID "6E400001-B5A3-F393-E0A9-E50E24DCCA9E" // UART service UUID
#define CHARACTERISTIC_UUID_RX "6E400002-B5A3-F393-E0A9-E50E24DCCA9E"
#define CHARACTERISTIC_UUID_TX "6E400003-B5A3-F393-E0A9-E50E24DCCA9E"
//#define SERVICE_UUID "025A7775-49AA-42BD-BBDB-E2AE77782966" // Black Widow BLE
//#define CHARACTERISTIC_UUID_RX "A9CD2F86-8661-4EB1-B132-367A3434BC90"
//#define CHARACTERISTIC_UUID_TX "F38A2C23-BC54-40FC-BED0-60EDDA139F47"
//#define SERVICE_UUID "4fafc201-1fb5-459e-8fcc-c5c9c331914b"
//#define CHARACTERISTIC_UUID "beb5483e-36e1-4688-b7f5-ea07361b26a8"
class MyServerCallbacks: public BLEServerCallbacks {
void onConnect(BLEServer* pServer) {
deviceConnected = true;
};
void onDisconnect(BLEServer* pServer) {
deviceConnected = false;
}
};
class MyCallbacks: public BLECharacteristicCallbacks {
void onWrite(BLECharacteristic *pCharacteristic) {
std::string rxValue = pCharacteristic->getValue();
// Serial.println("DXDXDX");
if (rxValue.length() > 0) {
Serial.println("*********");
Serial.print("Received Value: ");
for (int i = 0; i < rxValue.length(); i++)
Serial.print(rxValue[i]);
Serial.println();
Serial.println("*********");
}
if(rxValue == "ON")
{
Serial.println("Turning ON the led");
digitalWrite(LED_BUILTIN,HIGH);
}
if(rxValue == "OFF")
{
Serial.println("Turning OFF the led");
digitalWrite(LED_BUILTIN,LOW);
}
}
};
void setup() {
Serial.begin(115200);
pinMode(LED_BUILTIN,OUTPUT);
// Create the BLE Device
BLEDevice::init("DX-LED");
// Create the BLE Server
pServer = BLEDevice::createServer();
pServer->setCallbacks(new MyServerCallbacks());
// Create the BLE Service
BLEService *pService = pServer->createService(SERVICE_UUID);
// Create a BLE Characteristic
pTxCharacteristic = pService->createCharacteristic(
CHARACTERISTIC_UUID_TX,
BLECharacteristic::PROPERTY_NOTIFY
);
pTxCharacteristic->addDescriptor(new BLE2902());
BLECharacteristic * pRxCharacteristic = pService->createCharacteristic(
CHARACTERISTIC_UUID_RX,
BLECharacteristic::PROPERTY_WRITE
| BLECharacteristic::PROPERTY_WRITE_NR
);
pRxCharacteristic->setReadProperty(true);
pRxCharacteristic->setWriteProperty(true);
pRxCharacteristic->setCallbacks(new MyCallbacks());
// pCharacteristic = pService->createCharacteristic(
// CHARACTERISTIC_UUID,
// BLECharacteristic::PROPERTY_READ |
// BLECharacteristic::PROPERTY_WRITE |
// BLECharacteristic::PROPERTY_NOTIFY |
// BLECharacteristic::PROPERTY_INDICATE
// );
// pCharacteristic->addDescriptor(new BLE2902());
// pCharacteristic->setReadProperty(true);
// pCharacteristic->setWriteProperty(true);
// pCharacteristic->setCallbacks(new MyCallbacks());
// Start the service
pService->start();
// Start advertising
pServer->getAdvertising()->start();
Serial.println("Waiting a client connection to notify...");
}
void loop() {
if (deviceConnected) {
pCharacteristic->setValue(&txValue, 1);
pCharacteristic->notify();
txValue++;
delay(100); // bluetooth stack will go into congestion, if too many packets are sent
}
// disconnecting
if (!deviceConnected && oldDeviceConnected) {
delay(500); // give the bluetooth stack the chance to get things ready
pServer->startAdvertising(); // restart advertising
Serial.println("start advertising");
oldDeviceConnected = deviceConnected;
}
// connecting
if (deviceConnected && !oldDeviceConnected) {
// do stuff here on connecting
oldDeviceConnected = deviceConnected;
}
}
其中UUID是BLE协议规定的服务标识号,注明了服务提供的数据接口。
//#define SERVICE_UUID "025A7775-49AA-42BD-BBDB-E2AE77782966" // Black Widow BLE
//#define CHARACTERISTIC_UUID_RX "A9CD2F86-8661-4EB1-B132-367A3434BC90"
//#define CHARACTERISTIC_UUID_TX "F38A2C23-BC54-40FC-BED0-60EDDA139F47"
应用中需要将ESP32_BLE开源库复制到项目目录下,开源库地址:https://github.com/nkolban/ESP32_BLE_Arduino
Flutter作为一个跨平台应用框架,提供了对ios及android平台的Bluetooth的支持。
简单的操作代码-main.dart为:
// Copyright 2017, Paul DeMarco.
// All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter_blue/flutter_blue.dart';
import 'package:flutter_blue_example/widgets.dart';
void main() {
runApp(new FlutterBlueApp());
}
class FlutterBlueApp extends StatefulWidget {
FlutterBlueApp({Key key, this.title}) : super(key: key);
final String title;
@override
_FlutterBlueAppState createState() => new _FlutterBlueAppState();
}
class _FlutterBlueAppState extends State<FlutterBlueApp> {
FlutterBlue _flutterBlue = FlutterBlue.instance;
/// Scanning
StreamSubscription _scanSubscription;
Map<DeviceIdentifier, ScanResult> scanResults = new Map();
bool isScanning = false;
/// State
StreamSubscription _stateSubscription;
BluetoothState state = BluetoothState.unknown;
/// Device
BluetoothDevice device;
bool get isConnected => (device != null);
StreamSubscription deviceConnection;
StreamSubscription deviceStateSubscription;
List<BluetoothService> services = new List();
Map<Guid, StreamSubscription> valueChangedSubscriptions = {};
BluetoothDeviceState deviceState = BluetoothDeviceState.disconnected;
@override
void initState() {
super.initState();
// Immediately get the state of FlutterBlue
_flutterBlue.state.then((s) {
setState(() {
state = s;
});
});
// Subscribe to state changes
_stateSubscription = _flutterBlue.onStateChanged().listen((s) {
setState(() {
state = s;
});
});
}
@override
void dispose() {
_stateSubscription?.cancel();
_stateSubscription = null;
_scanSubscription?.cancel();
_scanSubscription = null;
deviceConnection?.cancel();
deviceConnection = null;
super.dispose();
}
@override
Widget build(BuildContext context) {
var tiles = new List<Widget>();
if (state != BluetoothState.on) {
tiles.add(_buildAlertTile());
}
if (isConnected) {
tiles.add(_buildDeviceStateTile());
tiles.addAll(_buildServiceTiles());
} else {
tiles.addAll(_buildScanResultTiles());
}
return new MaterialApp(
home: new Scaffold(
appBar: new AppBar(
title: const Text('FlutterBlue'),
actions: _buildActionButtons(),
),
floatingActionButton: _buildScanningButton(),
body: new Stack(
children: <Widget>[
(isScanning) ? _buildProgressBarTile() : new Container(),
new ListView(
children: tiles,
)
],
),
),
);
}
}
...
widgets.dart为:
// Copyright 2017, Paul DeMarco.
// All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
import 'package:flutter/material.dart';
import 'package:flutter_blue/flutter_blue.dart';
class ScanResultTile extends StatelessWidget {
const ScanResultTile({Key key, this.result, this.onTap}) : super(key: key);
final ScanResult result;
final VoidCallback onTap;
Widget _buildTitle(BuildContext context) {
if (result.device.name.length > 0) {
return Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(result.device.name),
Text(
result.device.id.toString(),
style: Theme.of(context).textTheme.caption,
)
],
);
} else {
return Text(result.device.id.toString());
}
}
Widget _buildAdvRow(BuildContext context, String title, String value) {
return Padding(
padding: const EdgeInsets.symmetric(horizontal: 16.0, vertical: 4.0),
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(title, style: Theme.of(context).textTheme.caption),
SizedBox(
width: 12.0,
),
Expanded(
child: Text(
value,
style: Theme.of(context)
.textTheme
.caption
.apply(color: Colors.black),
softWrap: true,
),
),
],
),
);
}
...
手机应用启动后,连接ESP32通过注册的的服务,可以向ESP32发送指令,本示例中手机发送“ON”或“OFF”可以控制ESP32一个管脚的的高低电平。